package _20250305;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyThread6 {
    /**
     * 设计一个多线程程序模拟银行转账操作。有多个线程同时进行转账操作，
     * 从一个账户向另一个账户转账一定金额。要求使用锁机制确保转账过程的原子性和线程安全，同时考虑死锁的可能性并避免死锁 。
     */
    public static void main(String[] args) {
        Account account1=new Account(123,5000);
        Account account2=new Account(234,0);
        for (int i=0;i<10;i++) {
            new Thread(new transferAccounts(account1,account2,500)).start();
            new Thread(new transferAccounts(account1,account2,500)).start();
            new Thread(new transferAccounts(account1,account2,500)).start();
            new Thread(new transferAccounts(account1,account2,500)).start();
            new Thread(new transferAccounts(account1,account2,500)).start();
            new Thread(new transferAccounts(account2,account1,500)).start();
        }


    }

    private static class Account{


        int ID;
        int balance;
        private final Lock lock=new ReentrantLock();

        public Account(int ID, int balance) {
            this.ID = ID;
            this.balance = balance;
        }
        public Account() {
        }

        public int  getID() {
            return ID;
        }

        public void setID(int  ID) {
            this.ID = ID;
        }

        public int getBalance() {
            return balance;
        }

        public void setBalance(int balance) {
            this.balance = balance;
        }

        /**
         * 存款
         */
        public void deposit(int amount){
            lock.lock();
            try{
                balance+=amount;
            } finally {
                lock.unlock();
            }
        }
        /**
         * 取款
         */
        public void withdraw(int amount){
            lock.lock();
            try{
                balance-=amount;
            } finally {
                lock.unlock();
            }
        }

    }


    private static class transferAccounts implements Runnable {
        private final Account fromAccount;
        private final Account toAccount;
        private final int amount;
        public transferAccounts(Account fromAccount, Account toAccount, int amount) {
            this.fromAccount = fromAccount;
            this.toAccount = toAccount;
            this.amount = amount;
        }
        @Override
        public void run() {
            transfer(fromAccount,toAccount,amount);
        }

        private void transfer(Account fromAccount, Account toAccount, int amount) {
            /**
             * 避免死锁，按账户ID顺序加锁
             */
            Account firstLock = fromAccount.getID() < toAccount.getID() ? fromAccount : toAccount;
            Account secondLock = fromAccount.getID() < toAccount.getID() ? toAccount : fromAccount;
            firstLock.lock.lock();
            try {
                secondLock.lock.lock();
                try {
                    if (fromAccount.getBalance() >= amount) {
                        fromAccount.withdraw(amount);
                        toAccount.deposit(amount);
                        System.out.println(fromAccount.ID + "成功转账" + amount + "至" + toAccount.ID);
                        System.out.println(fromAccount.ID + "账户余额" + fromAccount.balance);
                        System.out.println(toAccount.ID + "账户余额" + toAccount.balance);
                        System.out.println("--------------------------------------");
                    } else {
                        System.out.println("失败");
                        System.out.println("--------------------------------------");
                    }
                } finally {
                    secondLock.lock.unlock();
                }
            } finally {
                firstLock.lock.unlock();
            }


        }
    }
}
